<?php

namespace app\api\controller\database;

use app\api\controller\Api;
use app\common\database\model\Tables;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use util\Format;

class Source extends Api
{
    /**
     * 获取数据源信息
     * @return \think\response\Json
     */
    public function getSource(): \think\response\Json
    {
        $post = $this->request->post();
        $table = $post['table'];
        try {
            $source = Db::table('tk_table_source')->where('table', $table)->find();
            // 字段 转换
            $source['fields'] = json_decode($source['fields'], true);
        } catch (DbException $e) {
            return error([],'获取失败');
        }
        return success($source);
    }

    /**
     * 设置数据源
     * @return \think\response\Json
     */
    public function setSource(): \think\response\Json
    {
        $post = $this->request->post();

        $post['fields'] = json_encode($post['fields']);
        try {
            // tk_table_source
            // 查找是否存在
            $source = Db::table('tk_table_source')->where('table', $post['table'])->find();

            if ($source) {
                // 更新
                Db::table('tk_table_source')->where('table', $post['table'])->update($post);
            } else {
                // 插入
                Db::table('tk_table_source')->insert($post);
            }

            // update tk_tables's source field
            Db::table('tk_tables')->where('name', $post['table'])->update(['source' => $post['title']]);

        } catch (DbException $e) {
            return error([],'设置失败');
        }

        return success([], '设置成功');
    }


    /**
     * 获取所有数据源
     * @return \think\response\Json
     */
    public function index(): \think\response\Json
    {
        try {
            $sources = Db::table('tk_table_source')->field('table, title')->select();
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
            return success([],'暂无数据源');
        }

        return success($sources);
    }

    /**
     * 根据表名获取数据源的数据
     * @return \think\response\Json
     */
    public function items(): \think\response\Json
    {
        $post = $this->request->post();
        $table_name = $post['table'];
        try {
            $source = Db::table('tk_table_source')->where('table', $table_name)->find();
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
            return success([],'暂无数据源');
        }

        $fields = json_decode($source['fields'], true);
        try {
            $items = Db::table($table_name)->field($fields)->select();
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
            return success([],'暂无数据源');
        }
        return success($items);
    }

    /**
     * 获取common下的所有目录
     */
    public function catalog(): \think\response\Json
    {
        // 获取common目录下的所有目录
        $commonPath = app()->getBasePath() . 'common';
        $dirs = [];
        if (is_dir($commonPath)) {
            $items = scandir($commonPath);
            foreach ($items as $item) {
                if ($item != '.' && $item != '..' && is_dir($commonPath . '/' . $item)) {
                   // 获取目录名，我要包含app\common
                   $dir = 'app\\common\\' . $item;
                   $dirs[] = $dir;
                }
            }
        }

        return success($dirs);
    }

     /**
     * 获取所有的models
     */
    public function models(): \think\response\Json
    {
        // 获取common目录下包含model文件夹的目录下的所有文件
        $files = glob(app()->getBasePath() . 'common/*/model/*.php');
        $models = [];
        foreach ($files as $file) {
            $name = basename($file, '.php');
            $namespace = str_replace(app()->getBasePath(), 'app\\', dirname($file));
            $models[] = [
                'name' => $name,
                'namespace' => $namespace,
            ];
        }
        return success($models);
    }


    /**
     *创建model
     */
    public function buildModel()
    {
        $post = $this->request->post();
        $catalog = $post['catalog'];
        $table = $post['table'];

        // 获取表结构
        try {
            $fields = Db::query("SHOW FULL COLUMNS FROM " . $table);
        } catch (DbException $e) {
            return error([], '获取表结构失败');
        }

        // 获取配置信息表前缀 
        $config = config('database.connections.mysql');
        $prefix = $config['prefix'];
        // 去掉前缀
        $tableName = str_replace($prefix, '', $table);

        // 生成命名空间 + model 
        $namespace = str_replace('/', '\\', $catalog) . '\\model';
        
        // 获取表名作为类名
        $className = ucwords(str_replace('_', ' ', $tableName));
        $className = str_replace(' ', '', $className);

        // 生成Model文件内容
        $content = "<?php\n\n";
        $content .= "namespace {$namespace};\n\n";
        $content .= "use think\\Model;\n\n";
        // 如果存delete_time 引用SoftDelete
        if (in_array('delete_time', array_column($fields, 'Field'))) {
            $content .= "use think\\model\\concern\\SoftDelete;\n\n";
        }
        $content .= "class {$className} extends Model\n";
        $content .= "{\n";
        $content .= "    protected \$table = '{$table}';\n\n";
        
        // 如果存在以date,time,datetime结尾的字段,但是不包含delete_time、create_time、update_time，则添加 protected $type = ['datetime' => 'timestamp']
        $type = [];
        foreach ($fields as $field) {
            if (preg_match('/date|time|datetime$/', $field['Field']) && !in_array($field['Field'], ['delete_time', 'create_time', 'update_time'])) {
                $type[$field['Field']] = 'timestamp';
            }
        }

        // 如果字段类型是json，则添加 protected $type = ['json' => 'json'];
        foreach ($fields as $field) {
            if ($field['Type'] == 'json') {
                $type[$field['Field']] = 'json';
            }
        }

        // 生成protected $type
        $content .= "    protected \$type = [";
        foreach ($type as $key => $value) {
            $content .= "        '{$key}' => '{$value}',";
        }
        $content .= "    ];\n";

        // 如果存在delete_time字段，则添加软删除
        if (in_array('delete_time', array_column($fields, 'Field'))) {
            $content .= "    use SoftDelete;\n";
            $content .= "    protected \$defaultSoftDelete = 0;\n";
        }
        
            $content .= "}\n";

        // 获取项目根目录下的model目录 
        $modelPath =  app()->getRootPath() . $catalog . '\\model';

        if (!is_dir($modelPath)) {
            mkdir($modelPath, 0777, true);
        }

        // 写入文件
        $filePath = $modelPath . '/' . $className . '.php';
        if (file_put_contents($filePath, $content) === false) {
            return error([], '文件写入失败');
        }

        return success([], '生成成功');
    
    }
}